package springboot.com.dao;

import java.io.Serializable;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaQuery;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.util.CollectionUtils;

import springboot.com.utils.jpa.JpaCriteriaBuilder;
import springboot.com.utils.jpa.PagingVO;



@SuppressWarnings("rawtypes")
public  abstract class BaseDao<K extends JpaRepository, T extends Serializable> { 

	public K jpaRepository;

	public K getJpaRepository() {
		return jpaRepository;
	}

	public void setJpaRepository(K jpaRepository) {
		this.jpaRepository = jpaRepository;
	}
	
	
	/**
	 * find Object By Serializable Id
	 *
	 * @param id
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public T selectById(Serializable id) {
		return (T) jpaRepository.findOne(id);
	}
	
	
	/**
	 * select All entity
	 *
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public List<T> findAll() {
		return jpaRepository.findAll();
	}

	/**
	 * save entity
	 *
	 * @param entity
	 */

	@SuppressWarnings("unchecked")
	public T save(T entity) {
		Object savedEntity = jpaRepository.saveAndFlush(entity);
		return (T) savedEntity;
	}

	/**
	 * 
	 * @param query
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <E> E findSingle(Query query) {

		query.setFirstResult(0).setMaxResults(1);
		return (E) query.getSingleResult();
	}

	/**
	 * 
	 * @param list
	 * @return
	 * 
	 * 		Date:2016年3月16日上午11:52:21
	 * 
	 * @author Forever
	 *
	 */
	public T selectTopOne(List<T> list) {
		return !(CollectionUtils.isEmpty(list)) ? list.get(0) : null;
	}

	@SuppressWarnings("unchecked")
	public void update(T entity) {
		jpaRepository.saveAndFlush(entity);
	}

	public PagingVO selectPagingVO(JpaCriteriaBuilder queryBuilder, EntityManager entityManager, PagingVO page,
			JpaCriteriaBuilder countBuilder) {

		page.setDetails(selectPaging(queryBuilder, entityManager, page));
		page.setCount(count(countBuilder, entityManager));
		return page;
	}

	public Long count(JpaCriteriaBuilder builder, EntityManager entityManager) {

		// Projections.sqlProjection(sql, columnAliases, types)
		List<T> counts = selectE(builder, entityManager);
		return (long) (CollectionUtils.isEmpty(counts) ? 0 : counts.size());

	}

	@SuppressWarnings("unchecked")
	public List<T> selectPaging(JpaCriteriaBuilder builder, EntityManager entityManager, PagingVO page) {
		builder.setOrder(page.getOrderName());
		CriteriaQuery<T> criteriaQuery = builder.newCriteriaQuery();
		TypedQuery<T> query = entityManager.createQuery(criteriaQuery);
		int index = Integer.parseInt(page.getPageIndex());
		int size = Integer.parseInt(page.getPageSize());
		return query.setFirstResult((index - 1) * size).setMaxResults(size).getResultList();
	}

	@SuppressWarnings("unchecked")
	public List<T> selectE(JpaCriteriaBuilder builder, EntityManager entityManager) {
		CriteriaQuery<T> criteriaQuery = builder.newCriteriaQuery();
		TypedQuery<T> query = entityManager.createQuery(criteriaQuery);
		return query.getResultList();
	}

}
